package com.x.uikit.page;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class StrongListeners<Listener> {
    private final Map<String, Listener> mListeners = new ConcurrentHashMap<>();
    private final Handler mUIHandler = new Handler(Looper.getMainLooper());

    private String key(@NonNull Listener listener) {
        return String.valueOf(listener.hashCode());
    }

    public void addListener(final Listener listener) {
        if (listener == null) {
            return;
        }
        runInUIThread(new Runnable() {
            @Override
            public void run() {
                mListeners.put(key(listener), listener);
            }
        });

    }

    public void clear() {
        mListeners.clear();
    }

    private void runInUIThread(@NonNull Runnable runnable) {
        if (Looper.getMainLooper() == Looper.myLooper()) {
            runnable.run();
        } else {
            mUIHandler.post(new Runnable() {
                @Override
                public void run() {
                    runnable.run();
                }
            });
        }
    }

    public void removeListener(Listener listener) {
        if (listener == null) {
            return;
        }
        runInUIThread(new Runnable() {
            @Override
            public void run() {
                mListeners.remove(key(listener));
            }
        });

    }

    public void callback(ICallbackTask<Listener> callTask) {
        runInUIThread(new Runnable() {
            @Override
            public void run() {
                handleCallback(callTask);
            }
        });
    }

    public void callbackPost(ICallbackTask<Listener> callTask) {
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                handleCallback(callTask);
            }
        });
    }

    public void callbackAndClear(ICallbackTask<Listener> callTask) {
        runInUIThread(new Runnable() {
            @Override
            public void run() {
                handleCallback(callTask);
                clear();
            }
        });
    }

    private void handleCallback(ICallbackTask<Listener> callTask) {
        if (mListeners.size() > 0) {
            Iterator<String> iterator = mListeners.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                Listener listener = mListeners.get(key);
                if (listener != null) {
                    callTask.run(listener);
                } else {
                    iterator.remove();
                }
            }
        }
    }

    public interface ICallbackTask<Listener> {
        void run(@NonNull Listener listener);
    }


}